<template>
  <transition :name="transitionName" appear="appear">
    <div class="w-notification" v-if="show" :class="classes" :style="styles">
      <w-alert
        v-bind="alertProps"
        @update:model-value="
          $emit('update:modelValue', false);
          $emit('input', false);
        "
      >
        <slot></slot>
      </w-alert>
    </div>
  </transition>
</template>

<script>
  import { ref, computed, watch } from "vue";
  export default {
    name: "w-notification",

    props: {
      // Notification props.
      modelValue: { default: true }, // Show or hide.
      transition: { type: [String, Boolean], default: "" },
      timeout: { type: [Number, String], default: 0 },
      absolute: { type: Boolean },
      top: { type: Boolean },
      bottom: { type: Boolean },
      left: { type: Boolean },
      right: { type: Boolean },
      zIndex: { type: [Number, String, Boolean] },
      // Alert props.
      success: { type: Boolean },
      info: { type: Boolean },
      warning: { type: Boolean },
      error: { type: Boolean },
      color: { type: String },
      bgColor: { type: String },
      shadow: { type: Boolean },
      tile: { type: Boolean },
      round: { type: Boolean },
      plain: { type: Boolean },
      noBorder: { type: Boolean },
      borderLeft: { type: Boolean },
      borderRight: { type: Boolean },
      borderTop: { type: Boolean },
      borderBottom: { type: Boolean },
      outline: { type: Boolean },
      dismiss: { type: Boolean },
      xs: { type: Boolean },
      sm: { type: Boolean },
      md: { type: Boolean },
      lg: { type: Boolean },
      xl: { type: Boolean },
    },

    emits: ["input", "update:modelValue", "close"],
    setup(props, ctx) {
      const show = ref(props.modelValue);
      const timeoutId = ref(null);

      const transitionName = computed(() => {
        if (props.transition === false) return "";
        if (!props.transition) {
          const opposites = {
            top: "down",
            bottom: "up",
            left: "right",
            right: "left",
          };
          return `slide-${
            opposites[position.value[position.value[1] === "center" ? 0 : 1]]
          }`;
        }

        return props.transition;
      });

      const position = computed(() => {
        let position = [];
        if (!props.top && !props.bottom && !props.left && !props.right)
          position = ["top", "right"];
        else
          position = [
            (props.top && "top") || (props.bottom && "bottom") || "top",
            (props.left && "left") || (props.right && "right") || "center",
          ];
        return position;
      });

      const hasType = computed(() => {
        return !!(props.success || props.info || props.warning || props.error);
      });

      const alertProps = computed(() => {
        return {
          modelValue: show.value,
          success: props.success,
          info: props.info,
          warning: props.warning,
          error: props.error,
          color: props.color,
          bgColor: props.bgColor || (!hasType.value && "white") || "",
          shadow: props.shadow,
          tile: props.tile,
          round: props.round,
          plain: props.plain,
          noBorder: props.noBorder,
          borderLeft: props.borderLeft,
          borderRight: props.borderRight,
          borderTop: props.borderTop,
          borderBottom: props.borderBottom,
          outline: props.outline,
          dismiss: props.dismiss,
          xs: props.xs,
          sm: props.sm,
          md: props.md,
          lg: props.lg,
          xl: props.xl,
        };
      });

      const classes = computed(() => {
        return {
          "w-notification--absolute": props.absolute,
          [`w-notification--${position.value.join(" w-notification--")}`]: true,
        };
      });

      const styles = computed(() => {
        return {
          zIndex: props.zIndex || props.zIndex === 0 || null,
        };
      });

      const timeoutVal = computed(() => {
        return parseInt(props.timeout);
      });

      if (props.modelValue && timeoutVal.value) {
        countdown();
      }

      function countdown() {
        timeoutId.value = setTimeout(() => {
          ctx.emit("update:modelValue", (show.value = false));
          ctx.emit("input", false);
          ctx.emit("close");
        }, timeoutVal.value);
      }
      watch(
        () => props.modelValue,
        (value) => {
          clearTimeout(timeoutId.value);
          show.value = value;

          if (value && timeoutVal.value) {
            countdown();
          }
        }
      );
      return {
        show,
        timeoutId,
        transitionName,
        position,
        hasType,
        alertProps,
        classes,
        styles,
        timeoutVal,
      };
    },
  };
</script>
